package com.soriya.nestlive.screen.live

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.opengl.GLSurfaceView
import android.os.Build
import android.util.Log
import android.view.ViewGroup
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.LocalContentColor
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.Slider
import androidx.compose.material.TextField
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.AutoFixHigh
import androidx.compose.material.icons.filled.Cameraswitch
import androidx.compose.material.icons.filled.MusicNote
import androidx.compose.material.icons.filled.PowerSettingsNew
import androidx.compose.material.icons.outlined.Image
import androidx.compose.material.icons.twotone.Message
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ksyun.media.streamer.capture.CameraCapture
import com.ksyun.media.streamer.capture.camera.CameraTouchHelper
import com.ksyun.media.streamer.filter.imgtex.ImgBeautySmoothFilter
import com.ksyun.media.streamer.filter.imgtex.ImgFilterBase
import com.ksyun.media.streamer.kit.KSYStreamer
import com.ksyun.media.streamer.kit.StreamerConstants
import com.soriya.nestlive.R
import com.soriya.nestlive.component.CameraLiveTitleEdit
import com.soriya.nestlive.component.CustomEditText
import com.soriya.nestlive.component.CustomImage
import com.soriya.nestlive.component.LiveChatArea
import com.soriya.nestlive.component.LiveOptionButton
import com.soriya.nestlive.component.LiveTitle
import com.soriya.nestlive.component.MediumText
import com.soriya.nestlive.component.MediumTitle
import com.soriya.nestlive.component.ScreenColumnContent
import com.soriya.nestlive.component.ScreenConstraintContent
import com.soriya.nestlive.component.SmallText
import com.soriya.nestlive.component.SmallTitle
import com.soriya.nestlive.component.SmallerText
import com.soriya.nestlive.constant.CommonConstant
import com.soriya.nestlive.constant.ServerConstant
import com.soriya.nestlive.constant.StreamConstant
import com.soriya.nestlive.constant.UIValue
import com.soriya.nestlive.extend.toFormatString
import com.soriya.nestlive.im.MessageType
import com.soriya.nestlive.im.NettyClient
import com.soriya.nestlive.im.message.IMMessage
import com.soriya.nestlive.model.Category
import com.soriya.nestlive.model.Channel
import com.soriya.nestlive.model.Live
import com.soriya.nestlive.model.LiveChat
import com.soriya.nestlive.util.ToastUtil
import com.soriya.nestlive.viewmodel.BeautyConfigModel
import com.soriya.nestlive.viewmodel.ChannelModel
import com.soriya.nestlive.viewmodel.LiveChatModel
import com.soriya.nestlive.viewmodel.LiveModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.File
import java.util.Date
import java.util.Timer
import java.util.TimerTask
import javax.inject.Inject

private val PERMISSIONS = arrayOf(
    Manifest.permission.CAMERA,
    Manifest.permission.RECORD_AUDIO
)

@OptIn(ExperimentalMaterialApi::class)
@Composable
@Preview
fun CameraStreamInfoScreen() {
    val context: Activity = LocalContext.current as Activity

    // 美颜ViewModel
    val beautyConfigModel: BeautyConfigModel = viewModel()
    val grindRatio = beautyConfigModel.grindRatio
    val whitenRatio = beautyConfigModel.whitenRatio
    val ruddyRatio = beautyConfigModel.ruddyRatio

    var glSurfaceView: GLSurfaceView // 预览视图

    var isLive by remember {
        mutableStateOf(false)
    }

    val liveChatModel: LiveChatModel = hiltViewModel()
    lateinit var timer: Timer

    val channelModel: ChannelModel = hiltViewModel()
    val liveModel: LiveModel = hiltViewModel()

    val myChannel by channelModel.channelDetail.collectAsState()

    LaunchedEffect(Unit) {
        channelModel.getMyChannel()
    }

    if (myChannel == null || myChannel == Channel.EMPTY) return

    // 推流实例
    val ksyStreamer = KSYStreamer(context).apply {

        // 设置预览分辨率, 当一边为0时，SDK会根据另一边及实际预览View的尺寸进行计算
        setPreviewResolution(540, 0)
        // 设置推流分辨率，可以不同于预览分辨率（不应大于预览分辨率，否则推流会有画质损失）
        setTargetResolution(540, 0)
        // 设置预览帧率
        previewFps = 15F
        // 设置推流帧率，当预览帧率大于推流帧率时，编码模块会自动丢帧以适应设定的推流帧率
        targetFps = 15F
        // 设置视频码率，分别为初始平均码率、最高平均码率、最低平均码率，单位为kbps，另有setVideoBitrate接口，单位为bps
        setVideoKBitrate(600, 800, 400)
        // 设置音频采样率
        audioSampleRate = 44100
        // 设置音频码率，单位为kbps，另有setAudioBitrate接口，单位为bps
        setAudioKBitrate(48)
        /**
         * 设置编码模式(软编、硬编)，请根据白名单和系统版本来设置软硬编模式，不要全部设成软编或者硬编,白名单可以联系金山云商务:
         * StreamerConstants.ENCODE_METHOD_SOFTWARE
         * StreamerConstants.ENCODE_METHOD_HARDWARE
         */
        setEncodeMethod(StreamerConstants.ENCODE_METHOD_SOFTWARE)
        // 设置屏幕的旋转角度，支持 0, 90, 180, 270
        rotateDegrees = 0
        // 设置开始预览使用前置还是后置摄像头
        cameraFacing = CameraCapture.FACING_FRONT
        // 后台最后一帧
        enableRepeatLastFrame = false
        setOnInfoListener { what, msg1, msg2 ->
            Log.i("SoRiya", "InfoListener: $what, $msg1, $msg2")
        }
        setOnErrorListener { what, msg1, msg2 ->
            Log.i("SoRiya", "ErrorListener: $what, $msg1, $msg2")
        }
    }

    // 对焦/变焦
    val cameraTouchHelper = CameraTouchHelper()
    cameraTouchHelper.setCameraCapture(ksyStreamer.cameraCapture)
    cameraTouchHelper.setEnableZoom(true)
    cameraTouchHelper.setEnableTouchFocus(true)

    val filter = ImgBeautySmoothFilter(ksyStreamer.glRender, context) // 美颜实例
    val filters: List<ImgFilterBase> = listOf(
        filter
    )

    // 设置美颜参数
    ksyStreamer.imgTexFilterMgt.filter = filters
    filter.grindRatio = 0F
    filter.whitenRatio = 0F
    filter.ruddyRatio = 0F

    // 底部动作条
    val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)

    // 协程
    val coroutineScope = rememberCoroutineScope()

    // 申请权限
    val permissionLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestMultiplePermissions(),
        onResult = { isGranteds ->
            var allGranted = false
            for ((_, isGranted) in isGranteds) {
                allGranted = isGranted
            }
            if (allGranted) {
//                ksyStreamer.startCameraPreview()
                ToastUtil.show(context, "授权成功")
            } else {
                ToastUtil.show(context, "授权失败")
            }
        }
    )

    LaunchedEffect(Unit) {
        launch {

        }
        launch {
            grindRatio.collect {
                if (filter.isGrindRatioSupported) filter.grindRatio = it
            }
        }
        launch {
            whitenRatio.collect {
                if (filter.isWhitenRatioSupported) filter.whitenRatio = it
            }
        }
        launch {
            ruddyRatio.collect {
                if (filter.isRuddyRatioSupported) filter.ruddyRatio = it
            }
        }
    }

    val lifecycle = LocalLifecycleOwner.current.lifecycle

    DisposableEffect(Unit) {
        fun startPreview() {
            // 判断权限
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                var check = PackageManager.PERMISSION_GRANTED
                for (permission in PERMISSIONS) {
                    check = ContextCompat.checkSelfPermission(context, permission)
                    if (check != PackageManager.PERMISSION_GRANTED) break
                }
                val hasPermission = check == PackageManager.PERMISSION_GRANTED
                if (!hasPermission) {
                    // 没有全部的权限，申请权限
                    permissionLauncher.launch(PERMISSIONS)
                } else {
                    ksyStreamer.startCameraPreview()
                }
            }
        }

        val lifecycleObserver = LifecycleEventObserver { _, event ->
            Log.i("SoRiya", "Event: $event")
            when (event) {
                Lifecycle.Event.ON_CREATE -> {}
                Lifecycle.Event.ON_RESUME -> {
                    ksyStreamer.onResume()
                    ksyStreamer.stopImageCapture()
                    startPreview()
                    ksyStreamer.setUseDummyAudioCapture(false)
                }
                Lifecycle.Event.ON_PAUSE -> {
                    ksyStreamer.onPause()
                    ksyStreamer.stopCameraPreview()
                    ksyStreamer.startImageCapture("assets://bg.jpg")
                    ksyStreamer.setUseDummyAudioCapture(true)
                }
                Lifecycle.Event.ON_STOP -> {}
                Lifecycle.Event.ON_DESTROY -> {
                    ksyStreamer.release()
                    timer.cancel()
                }
                else -> {}
            }
        }
        lifecycle.addObserver(lifecycleObserver)

        onDispose {
            lifecycle.removeObserver(lifecycleObserver)
        }
    }


    @Composable
    fun DisplayPreview() {
        Image(
            painter = painterResource(id = R.mipmap.live_bg),
            contentScale = ContentScale.Crop,
            contentDescription = "Live Background",
            modifier = Modifier
                .fillMaxSize()
        )
        AndroidView(factory = { context ->
            glSurfaceView = GLSurfaceView(context)
            glSurfaceView.layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            // 设置预览View
            ksyStreamer.setDisplayPreview(glSurfaceView)
            glSurfaceView.setOnTouchListener(cameraTouchHelper)
            glSurfaceView
        })
    }

    @Composable
    fun DisplaySurface() {

        @Composable
        fun LiveOption(
            modifier: Modifier = Modifier
        ) = Column(
            modifier = modifier
        ) {
            // 翻转摄像头
            LiveOptionButton(icon = Icons.Default.Cameraswitch, contentDescription = "Cameras witch") {
                ksyStreamer.switchCamera()
            }

            // 美颜
            LiveOptionButton(icon = Icons.Default.AutoFixHigh, contentDescription = "Beauty") {
                coroutineScope.launch {
                    if (sheetState.isVisible)
                        sheetState.hide()
                    else
                        sheetState.show()
                }
            }

            // BGM
            LiveOptionButton(icon = Icons.Default.MusicNote, contentDescription = "BGM") {}
        }

        if (isLive) ScreenConstraintContent {
            val (title, option, mBottom, chat) = createRefs()

            LiveTitle(
                onExit = {
                    coroutineScope.launch {
                        liveModel.stopLive().collect {
                            timer.cancel()
                            ksyStreamer.stopStream()
                            isLive = false
                        }
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .constrainAs(title) {
                        top.linkTo(parent.top, margin = 20.dp)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
            )

            LiveOption(
                modifier = Modifier
                    .constrainAs(option) {
                        top.linkTo(title.bottom, margin = 10.dp)
                        end.linkTo(parent.end)
                    }
            )

            // chat
            LiveChatArea(
                channelId = myChannel!!.id!!, // TODO 自己的Channel
                modifier = Modifier
                    .constrainAs(chat) {
                        bottom.linkTo(mBottom.top, margin = 10.dp)
                        start.linkTo(parent.start)
                    }
            )

            Row(
                modifier = Modifier
                    .padding(bottom = UIValue.VERTICAL_PADDING)
                    .fillMaxWidth()
                    .height(60.dp)
                    .constrainAs(mBottom) {
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                        bottom.linkTo(parent.bottom)
                    }
            ) {
                LiveOptionButton(icon = Icons.TwoTone.Message, contentDescription = "Chat") {}
            }

        } else ScreenConstraintContent {
            val (title, option, button) = remember {
                createRefs()
            }

            CameraLiveTitleEdit(
                modifier = Modifier
                    .padding(top = 20.dp)
                    .constrainAs(title) {
                        top.linkTo(parent.top)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
            )

            LiveOption(
                modifier = Modifier
                    .constrainAs(option) {
                        top.linkTo(title.bottom)
                        end.linkTo(parent.end)
                    }
            )

            Button(
                onClick = {
//                    if (ksyStreamer.url == ServerConstant.RTMP_URL) {
//                        ToastUtil.show(context, "初始化直播失败")
//                        return@Button
//                    }
                    val streamingConfig = context.getSharedPreferences(CommonConstant.STREAMING_CONFIG_KEY, Context.MODE_PRIVATE)

                    val liveTitle = streamingConfig.getString("title", "") ?: ""

                    val cover = streamingConfig.getString("cover", "") ?: ""

//                    var category by remember {
//                        mutableStateOf<Category?>(null)
//                    }

                    val tags = streamingConfig.getString("tags", null)?.split("|")?.toMutableList() ?: mutableListOf()

                    val desc = streamingConfig.getString("desc", "") ?: ""

                    // 设置推流地址
                    ksyStreamer.url = ServerConstant.RTMP_URL + myChannel!!.id

                    val live = Live(
                        channelId = myChannel!!.id!!,
                        categoryId = 1768122606944280577L,
                        liveName = liveTitle,
                        liveDesc = desc,
                        cover = cover,
                        tags = tags.filter { it.isEmpty() }.joinToString("|"),
                        orientation = 1,
                        viewers = 0,
                        startTime = Date().toFormatString(),
                        duration = 0F
                    )

                    coroutineScope.launch {
                        liveModel.createLive(live, null).collectLatest { _live ->
                            _live?.let { live ->
                                val edit = streamingConfig.edit()
                                edit.putString("title", live.liveName)
                                edit.putString("cover", live.cover)
                                edit.putString("desc", live.liveDesc)
                                edit.putString("tags", live.tags)
                                edit.apply()
                            }
                            ksyStreamer.startStream()
                            isLive = true

                            timer = Timer()
                            timer.schedule(object : TimerTask() {
                                override fun run() {
                                    val imMessage = IMMessage(
                                        type = MessageType.STREAMING_HEART,
                                        from = myChannel!!.id!!,
                                        to = 0L,
                                        state = 1,
                                        nickname = null,
                                        data = null
                                    )
                                    liveChatModel.nettyClient.sendMessage(imMessage)
                                }
                            }, 0, 6000)
                        }
                    }
                },
                shape = RoundedCornerShape(50),
                modifier = Modifier
                    .fillMaxWidth()
                    .height(64.dp)
                    .padding(bottom = 20.dp)
                    .constrainAs(button) {
                        bottom.linkTo(parent.bottom)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
            ) {
                MediumText(text = "开始直播")
            }
        }
    }

    ModalBottomSheetLayout(
        sheetContent = {
            Column(
                modifier = Modifier.padding(horizontal = UIValue.HORIZONTAL_PADDING, vertical = UIValue.VERTICAL_PADDING)
            ) {
                Column(
                    verticalArrangement = Arrangement.SpaceBetween,
                    modifier = Modifier
                ) {
                    Row(
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        val grindRatioAsState by grindRatio.collectAsState()

                        SmallText(text = "磨皮")
                        Spacer(modifier = Modifier.width(10.dp))
                        Slider(value = grindRatioAsState, onValueChange = {
                            coroutineScope.launch {
                                beautyConfigModel.changeGrindRatio(it)
                            }
                        })
                    }
                    Row(
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        val whitenAsState by whitenRatio.collectAsState()

                        SmallText(text = "美白")
                        Spacer(modifier = Modifier.width(10.dp))
                        Slider(value = whitenAsState, onValueChange = {
                            coroutineScope.launch {
                                beautyConfigModel.changeWhitenRatio(it)
                            }
                        })
                    }
                    Row(
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        val ruddyAsState by ruddyRatio.collectAsState()

                        SmallText(text = "红润")
                        Spacer(modifier = Modifier.width(10.dp))
                        Slider(value = ruddyAsState, onValueChange = {
                            coroutineScope.launch {
                                beautyConfigModel.changeRuddyRatio(it)
                            }
                        })
                    }
                }

                Row {

                }
            }
        },
        sheetState = sheetState,
        sheetBackgroundColor = MaterialTheme.colors.background,
        scrimColor = Color.Transparent
    ) {
        DisplayPreview()
        DisplaySurface()
    }
}